// Copyright (C) 2022 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
//
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<广西木子科技有限公司>，授权编号：<NT220402151538>，代码指纹：<A.648883738.885>，技术对接人微信：<ID: Lingmuziyi>】
// 【授权寄送：<收件：李先生、地址：南宁市科园西十路11号国电智能大厦1101F、电话：17736659550、邮箱：yingshashou@vip.qq.com>】
//
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
//
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.x52im.rainbowchat.http.logic.dto;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

import com.eva.epc.common.util.CommonUtils;

/**
 * 时间显示工具类。本类可用于标准Java和Andriod平台中。
 *
 * @author Jack Jiang(http://www.52im.net/space-uid-1.html)
 * @since 7.1
 */
public class TimeToolKit {
    /**
     * 传入秒数，得到“mm:ss”样的字符串。
     * 目前主要用于Andriod端显示短视频的视频时长时使用，本方法也可用于任何标准Java的代码中。
     *
     * @param durationWithSecond 秒数
     * @return 形如“0:10”这样的字符串，表示10秒时长的短视频
     * @since 7.1
     */
    public static String getMMSSFromSS(int durationWithSecond) {
        if (durationWithSecond < 0) {
            return "00:00";
        }

        //format of minute
        String str_minute = String.format("%d", durationWithSecond / 60);
        //format of second
        String str_second = String.format("%02d", durationWithSecond % 60);
        //format of time
        String format_time = str_minute + ":" + str_second;
        return format_time;
    }

    /**
     * 不带时区信息的时间戳按当前默认时代转换成时间字串显示。
     *
     * @param timestampWithGMT 本时间戳为GMT标准时间，解决跨国跨时区问题，用于UI时客户端需要转换成自已
     *                         的时区后再使用哦，此字段存放的是java版无时间时间戳，形如：1510491984536）
     * @param timePattern      要转换的目标时间字串格式
     * @return 如果转换成功则返回指定样式的时间字串，否则返回""
     */
    public static String convertTimstampToDefaultTimeZone(String timestampWithGMT, String timePattern) {
        String dateTimeStrForDefaultZone = "";
        if (timestampWithGMT != null)
            dateTimeStrForDefaultZone = getTimeString(getDateTime(timestampWithGMT), timePattern);

        return dateTimeStrForDefaultZone;
    }

    /**
     * 返回指定pattern样的日期时间字符串。
     *
     * @param dt
     * @param pattern
     * @return 如果时间转换成功则返回结果，否则返回空字符串""
     */
    public static String getTimeString(Date dt, String pattern) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(pattern);//"yyyy-MM-dd HH:mm:ss"
            sdf.setTimeZone(TimeZone.getDefault());
            return sdf.format(dt);
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 将指定字符串时间戳转为Date对象。
     *
     * @param timestampWithGMT 本时间戳为GMT标准时间，解决跨国跨时区问题，用于UI时客户端需要转换成自已
     *                         的时区后再使用哦，此字段存放的是java版无时间时间戳，形如：1510491984536）
     * @return
     */
    public static Date getDateTime(String timestampWithGMT) {
        return getDateTime(CommonUtils.getLongValue(timestampWithGMT));
    }

    public static Date getDateTime(long timestampWithGMT) {
        return new Date(timestampWithGMT);
    }

    /**
     * 显示一个人性化的时间字串（本方法当前主要用于客户界面的消息时间显示时）。
     * <p>
     * 当此时间是当天时间则显示“时分”格式，如果是当年则显示“月时分”格式，如果是
     * 今年之前的则显示为“年月时分”格式。
     * <p>
     * 本方法当前主要用于Android客户端首页“消息界面”中显示离线消息的时间之用，目
     * 的是让时间显示尽可能短且人性化，仅此而已。
     *
     * @param dt NSDate对象
     * @return 如果转换成功则返回形如：“刚刚”、“12:01"、“03-01 12：01”、“2018-02-01 12：01”，否则返回""
     * @deprecated by {@link OfflineMsgDTO#getTimeStringAutoShort2(Date, boolean)}, @since 4.5
     */
    public static String getTimeStringAutoShort(Date srcDate) {
        String ret = "";

        try {
            GregorianCalendar gcCurrent = new GregorianCalendar();
            gcCurrent.setTime(new Date());
            int currentYear = gcCurrent.get(GregorianCalendar.YEAR);
            int currentMonth = gcCurrent.get(GregorianCalendar.MONTH);
            int currentDay = gcCurrent.get(GregorianCalendar.DAY_OF_MONTH);
//			System.out.println("【DEBUG-getTimeStringAutoShort】currentDate = "+gcCurrent.getTime().toLocaleString()
//					+" ,year = "+currentYear+" ,month="+currentMonth+", day="+currentDay);

            GregorianCalendar gcSrc = new GregorianCalendar();
            gcSrc.setTime(srcDate);
            int srcYear = gcSrc.get(GregorianCalendar.YEAR);
            int srcMonth = gcSrc.get(GregorianCalendar.MONTH);
            int srcDay = gcSrc.get(GregorianCalendar.DAY_OF_MONTH);
//			System.out.println("【DEBUG-getTimeStringAutoShort】gcSrc = "+gcSrc.getTime().toLocaleString()
//					+" ,year = "+srcYear+" ,month="+srcMonth+", day="+srcDay);

            // 当年
            if (currentYear == srcYear) {
                long currentTimestamp = gcCurrent.getTimeInMillis();
                long srcTimestamp = gcSrc.getTimeInMillis();

                // 相差时间（单位：毫秒）
                long delta = currentTimestamp - srcTimestamp;

                // 当天
                if (currentMonth == srcMonth && currentDay == srcDay) {
                    // 时间相差60秒以内
                    if (delta < 60 * 1000)
                        ret = "刚刚";
                    else
                        ret = getTimeString(srcDate, "HH:mm");
                }
                // 当年 && 当天之外的时间
                else {
                    if ((delta / (3600 * 1000)) > 24 && (delta / (3600 * 1000)) < 48)
                        ret = "昨天";
                    else if ((delta / (3600 * 1000)) > 48 && (delta / (3600 * 1000)) < 72)
                        ret = "前天";
                    else
                        ret = getTimeString(srcDate, "M/d");
                }
            } else
                ret = getTimeString(srcDate, "yy/M/d HH:mm");

//			System.out.println("【DEBUG-getTimeStringAutoShort】计算结果："+ret+" 【OK】");
        } catch (Exception e) {
            System.err.println("【DEBUG-getTimeStringAutoShort】计算出错：" + e.getMessage() + " 【NO】");
        }

        return ret;
    }

    /**
     * 仿照微信中的消息时间显示逻辑，将时间戳（单位：毫秒）转换为友好的显示格式.
     * <p>
     * 1）7天之内的日期显示逻辑是：今天(具体的“时间:分钟”样式)、昨天(-1d)、前天(-2d)、星期？（只显示总计7天之内的星期数，即<=-4d）；<br>
     * 2）7天之外（即>7天）的逻辑：当年(显示“M月/d日”)、去年及之前(显示“yy年/M月/d日”)。
     *
     * @param srcDate            要处理的源日期时间对象
     * @param mustIncludeTime    true表示输出的格式里一定会包含“时间:分钟”（如果是“当天”，则不受此参数控制，无条件包含时间分钟），否则不包含（参考微信，不包含时分的情况，用于首页“消息”中显示时）
     * @param timeWithSegmentStr 本参数仅在mustIncludeTime=true时有生效，表示在时间字符串前带上“上午”、“下午”、“晚上”这样的描述
     * @return 输出格式形如：“上午10:30”、“昨天 中午12:04”、“前天 晚上20:51”、“星期二 上午09:30”、“5月6日 上午11:09”、“20年5月6日 上午11:09”等形式
     * @since 4.5
     */
    public static String getTimeStringAutoShort2(Date srcDate, boolean mustIncludeTime, boolean timeWithSegmentStr) {
        String ret = "";

        try {
            boolean isChineseLanguage = isChineseLanguage();

            GregorianCalendar gcCurrent = new GregorianCalendar();
            gcCurrent.setTime(new Date());
            int currentYear = gcCurrent.get(GregorianCalendar.YEAR);
            int currentMonth = gcCurrent.get(GregorianCalendar.MONTH) + 1;
            int currentDay = gcCurrent.get(GregorianCalendar.DAY_OF_MONTH);
//			System.out.println("【DEBUG-getTimeStringAutoShort】currentDate = "+gcCurrent.getTime().toLocaleString()
//					+" ,year = "+currentYear+" ,month="+currentMonth+", day="+currentDay);

            GregorianCalendar gcSrc = new GregorianCalendar();
            gcSrc.setTime(srcDate);
            int srcYear = gcSrc.get(GregorianCalendar.YEAR);
            int srcMonth = gcSrc.get(GregorianCalendar.MONTH) + 1;
            int srcDay = gcSrc.get(GregorianCalendar.DAY_OF_MONTH);
//			System.out.println("【DEBUG-getTimeStringAutoShort】gcSrc = "+gcSrc.getTime().toLocaleString()
//					+" ,year = "+srcYear+" ,month="+srcMonth+", day="+srcDay);

            // 要额外显示的时间分钟
            String timeExtraStr = "";
            if (mustIncludeTime) {
//				String timePattern = "HH:mm";
//				// 原始的时间分钟字符串
//				String timeExtraStrOriginal = getTimeString(srcDate, timePattern);
//
//				// 时间段描述（形如：“上午”、“下午”、“晚上”这样的描述），只在中文语言下生效
//				String timeSegmentStr = "";
//				if(timeWithSegmentStr)
//					timeSegmentStr = isChineseLanguage?getTimeSegmentStr(timeExtraStrOriginal):"";
//
//				// 组合成最终的人性化时间分钟字符串形式
//				timeExtraStr = " "+timeSegmentStr+timeExtraStrOriginal;

                timeExtraStr = " " + getTimeHH24Human(srcDate, timeWithSegmentStr);
            }

            // 当年
            if (currentYear == srcYear) {
                long currentTimestamp = gcCurrent.getTimeInMillis();
                long srcTimestamp = gcSrc.getTimeInMillis();

                // 相差时间（单位：毫秒）
                long delta = (currentTimestamp - srcTimestamp);

                // 当天（月份和日期一致才是）
                if (currentMonth == srcMonth && currentDay == srcDay) {
//		        	// 时间相差60秒以内
//	                if(delta < 60 * 1000)
//	                    ret = "刚刚";
//	                // 否则当天其它时间段的，直接显示“时:分”的形式
//	                else
//	                    ret = getTimeString(srcDate, "HH:mm");

                    // 当天只需要显示时间分钟，且必须显示“上午”、“下午”这样的时间段描述
                    ret = getTimeHH24Human(srcDate, true);
                }
                // 当年 && 当天之外的时间（即昨天及以前的时间）
                else {
                    // 昨天（以“现在”的时候为基准-1天）
                    GregorianCalendar yesterdayDate = new GregorianCalendar();
                    yesterdayDate.add(GregorianCalendar.DAY_OF_MONTH, -1);

                    // 前天（以“现在”的时候为基准-2天）
                    GregorianCalendar beforeYesterdayDate = new GregorianCalendar();
                    beforeYesterdayDate.add(GregorianCalendar.DAY_OF_MONTH, -2);

                    // 用目标日期的“月”和“天”跟上方计算出来的“昨天”进行比较，是最为准确的（如果用时间戳差值
                    // 的形式，是不准确的，比如：现在时刻是2019年02月22日1:00、而srcDate是2019年02月21日23:00，
                    // 这两者间只相差2小时，直接用“delta/(3600 * 1000)” > 24小时来判断是否昨天，就完全是扯蛋的逻辑了）
                    if (srcMonth == (yesterdayDate.get(GregorianCalendar.MONTH) + 1)
                            && srcDay == yesterdayDate.get(GregorianCalendar.DAY_OF_MONTH)) {
                        ret = "昨天" + timeExtraStr;// -1d
                    }
                    // “前天”判断逻辑同上
                    else if (srcMonth == (beforeYesterdayDate.get(GregorianCalendar.MONTH) + 1)
                            && srcDay == beforeYesterdayDate.get(GregorianCalendar.DAY_OF_MONTH)) {
                        ret = "前天" + timeExtraStr;// -2d
                    } else {
                        // 跟当前时间相差的小时数
                        long deltaHour = (delta / (3600 * 1000));

                        // 如果小于 7*24小时就显示星期几
                        if (deltaHour < 7 * 24) {
                            String[] weekday = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};

                            // 取出当前是星期几
                            String weedayDesc = weekday[gcSrc.get(GregorianCalendar.DAY_OF_WEEK) - 1];
                            ret = weedayDesc + timeExtraStr;
                        }
                        // 否则直接显示完整日期时间
                        else
                            ret = getTimeString(srcDate, (isChineseLanguage() ? "M月d日" : "M/d")) + timeExtraStr;
                    }
                }
            } else
                ret = getTimeString(srcDate, (isChineseLanguage ? "yy年M月d日" : "yy/M/d")) + timeExtraStr;

//			System.out.println("【DEBUG-getTimeStringAutoShort】计算结果："+ret+" 【OK】");
        } catch (Exception e) {
            System.err.println("【DEBUG-getTimeStringAutoShort】计算出错：" + e.getMessage() + " 【NO】");
        }

        return ret;
    }

    /**
     * 获取仅包含“时间:分钟”部分的字符串，24小时制，且可以显示“上午”、“下午”、“晚上”这样的描述。
     *
     * @param srcDate
     * @param timeWithSegmentStr 表示在时间字符串前带上“上午”、“下午”、“晚上”这样的描述
     * @return 如果成功则返回结果，否则返回空字符串（不是null）
     */
    private static String getTimeHH24Human(Date srcDate, boolean timeWithSegmentStr) {
        String ret = "";

        try {
            String timePattern = "HH:mm";
            // 原始的时间分钟字符串
            String timeStr = getTimeString(srcDate, timePattern);

            // 时间段描述（形如：“上午”、“下午”、“晚上”这样的描述），只在中文语言下生效
            String timeSegmentStr = "";
            if (timeWithSegmentStr)
                timeSegmentStr = (isChineseLanguage() ? getTimeSegmentStr(timeStr) : "");

            // 组合成最终的人性化时间分钟字符串形式
            ret = timeSegmentStr + timeStr;
        } catch (Exception e) {
            System.err.println("【DEBUG-getTimeHH24Human】计算出错：" + e.getMessage() + " 【NO】");
        }

        return ret;
    }

    /**
     * 将一个两位24小时时间的转换为上午、下午这样的描述。
     *
     * @param hh24 两位的24小时制时间的小时部分
     * @return 如果成功转换则返回形如：“凌晨”、“上午”等，否则返回空字符串（不是null）
     * @since 7.1
     */
    private static String getTimeSegmentStr(String hh24) {
        String ret = "";
        if (hh24 != null && hh24.length() >= 2) {
            try {
                // 取出“小时”部分
                int a = Integer.parseInt(hh24.substring(0, 2));
                if (a >= 0 && a <= 6) {
                    ret = "凌晨";
                } else if (a > 6 && a <= 12) {
                    ret = "上午";
                } else if (a > 12 && a <= 13) {
                    ret = "中午";
                } else if (a > 13 && a <= 18) {
                    ret = "下午";
                } else if (a > 18 && a <= 24) {
                    ret = "晚上";
                }
            } catch (Exception e) {
                System.err.println("【DEBUG-getTimeSegmentStr】计算出错：" + e.getMessage() + " 【NO】");
            }
        }

        return ret;
    }

    /**
     * 判断当前系统语言是否是中文。
     *
     * @return true表示是是中文环境（不区分简繁体，否则不是）
     * @since 7.1
     */
    private static boolean isChineseLanguage() {
        boolean is = true;
        try {
            is = (Locale.getDefault().getLanguage().equals(new Locale("zh").getLanguage()));
        } catch (Exception e) {
            System.err.println("【DEBUG-isChineseLanguage】" + e.getMessage());
        }
        return is;
    }

    public static void main(String[] args) throws Exception {
//		String ddd = "2019-02-22 19:50";
//		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
//		Date d = sdf.parse(ddd);
//
//		System.out.println("结果："+OfflineMsgDTO.getTimeStringAutoShort2(d, true));

//		System.out.println(""+OfflineMsgDTO.isChineseLanguage());

//		System.out.println(new SimpleDateFormat("yyyy-MM-dd aHH:mm:ss").format(new Date()));
//
//		SimpleDateFormat sdf = new SimpleDateFormat("HH");//"yyyy-MM-dd HH:mm:ss"
//		sdf.setTimeZone(TimeZone.getDefault());
//		System.out.println(getTimeSegmentStr("23"));

//		System.out.println(getTimeHH24Human(new Date(), true));

//		System.out.println(TTT.getMMSSFromSS(6));
    }

}
